#pragma once

#include <pthread.h>
#include <functional>
#include <sys/types.h>
#include <unistd.h>

namespace ThreadModule
{
    using func_t = std::function<void(std::string name)>;
    //线程状态
    static int name_number = 1;
    enum TSTATUS
    {
        NEW,
        RUNNING,
        STOP
    };
    class Thread
    {
    private:
        //封装传入的fun_t任务，并且匹配pthread_create的参数类型
        static void* Routine(void* args)
        {
            Thread* t = static_cast<Thread*>(args);
            //变更线程状态，启动线程
            t->_status = RUNNING;
            t->_func(t->_name);
            return nullptr;
        }
    public:
        Thread(func_t func):_func(func),_status(NEW),_joinable(true)
        {
            _pid = ::getpid();
            _name = "thread - " + std::to_string(name_number++);
        }
        //启动线程
        bool Start()
        {
            if(_status != RUNNING)
            {
                int n = ::pthread_create(&_tid,nullptr,Routine,this);
                if(n != 0)
                    return false;
                return true;
            }
            return false;
        }
        // 停止线程
        bool Stop()
        {
            if(_status == TSTATUS::RUNNING)
            {
                int n = ::pthread_cancel(_tid);
                if(n != 0)
                    return false;
                _status = STOP;
                return true;
            }
            return false;
        }
        bool Join()
        {
            if(_joinable)
            {
                int n = ::pthread_join(_tid,nullptr);
                if(n!=0)
                    return false;
                _status = STOP;
                return true;
            }
            return false;
        }
        //分离线程
        void Detach()
        {
            pthread_detach(_tid);
            _joinable = false;
        }
        bool IsJoinable(){return _joinable;}
        std::string Name(){return _name;}
    private:
        std::string _name;
        pthread_t _tid;
        pid_t _pid;
        bool _joinable; //是否分离
        func_t _func;
        TSTATUS _status;
    };
}
